/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package system.log;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import javax.el.ELContext;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import system.general.Columna;
import system.general.Exc;
import system.general.Logged;
import system.general.Persistencia;

/**
 *
 * @author gilberto
 */
@ManagedBean(name = "system_logFind")
@FacesConverter(value = "system_logFind")
@RequestScoped
public class Find implements Converter {

    Logged logged;
    private Persistencia persistencia = new Persistencia();
    private Beans selectedBean = new Beans();
    private List<Beans> list = new ArrayList<>();
    private String sql = "";
    private String operator = " AND ";
    private String command = "SELECT * FROM ";
    private String table = "public.v_bitacora ";
    private String where = "";
    private String order = "ORDER BY nombre ";
    private Map<String, String> map = new HashMap();
    StringBuilder criteria = new StringBuilder("");

    public Find() {
        ELContext elContext = FacesContext.getCurrentInstance().getELContext();
        logged = (Logged) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, "logged");
    }

    public Beans getSelectedBean() {
        return selectedBean;
    }

    public void setSelectedBean(Beans selectedBeans) {
        this.selectedBean = selectedBeans;
    }

    public List<Beans> getListByLoggedMap() throws Exc, SQLException, Exception {
        operator = "AND";
        if (logged.getMap().isEmpty()) {
            return null;
        }
        return byMap(logged.getMap());
    }

    public List<Beans> getListByLoggedId() throws Exc, SQLException, Exception {
        if (logged.getMasterId() != 0) {
            operator = "AND";
            criteria = new StringBuilder();
            Map<String, String> map = new HashMap();
            map.put("id", String.valueOf(logged.getDetailId()));
            return byMap(map);
        }
        return null;
    }

    public boolean byExist(Map map) throws Exc, SQLException, Exception {
        criteria = new StringBuilder();
        List<Beans> listBean = byMap(map);
        if (listBean.isEmpty()) {
            listBean.clear();
            return false;
        }
        listBean.clear();
        return true;
    }

    public boolean byExistOther(Map map) throws Exc, SQLException, Exception {
        criteria = new StringBuilder();
        criteria.append("id <> ");
        criteria.append(String.valueOf(logged.getMasterId()));
        List<Beans> listBean = byMap(map);
        if (listBean.isEmpty()) {
            listBean.clear();
            return false;
        }

        listBean.clear();
        return true;
    }

    public List<Beans> byMap(Map map) throws Exc, SQLException, Exception {
        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            if (criteria.length() != 0) {
                criteria.append(operator);
            }
            where = "WHERE ";
            criteria.append(buildCriteria(e.getKey().toString(), e.getValue().toString()));
        }

        sql = command + table + where + criteria + order;

        criteria = new StringBuilder();
        return executeSql(sql);
    }

    private String buildCriteria(String llave, String valor) throws NoSuchFieldException {
        String attribe = llave;
        StringBuilder sqlItem = new StringBuilder("");
        if (attribe.contains(".")) {
            attribe = llave.substring(llave.indexOf(".") + 1, llave.length());
        }
        Field field = Beans.class.getDeclaredField(attribe);
        Annotation[] annotations = field.getDeclaredAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof Columna) {
                Columna myAnnotation = (Columna) annotation;
                switch (myAnnotation.tipo().toString()) {
                    case "String":
                        sqlItem.append(" lower(");
                        sqlItem.append(llave);
                        sqlItem.append(") SIMILAR TO '%(");
                        sqlItem.append((String) strChar(valor));
                        sqlItem.append(")%' ");
                        break;
                    case "Integer":
                        sqlItem.append(" ");
                        sqlItem.append(llave);
                        sqlItem.append(" = ");
                        sqlItem.append((String) valor);
                        break;
                    case "Boolean":
                        sqlItem.append(" ");
                        sqlItem.append(llave);
                        sqlItem.append(" = ");
                        sqlItem.append((String) valor);
                        break;
                    case "Date":
                        sqlItem.append(" ");
                        sqlItem.append(llave);
                        sqlItem.append(" = '");
                        sqlItem.append((String) valor);
                        sqlItem.append("' ");
                        break;
                    case "Timestamp":
                        sqlItem.append(" ");
                        sqlItem.append(llave);
                        sqlItem.append(" = '");
                        sqlItem.append((String) valor);
                        sqlItem.append("' ");
                        break;
                }
            }
        }
        return sqlItem.toString();
    }

    public List<Beans> executeSql(String sql) throws Exc, SQLException, Exception {
        list.clear();
        ResultSet rsts = persistencia.executeRsts(sql);
        //Actualiza la pantalla si encuentra el registro
        while (rsts.next()) {
            Beans beans = new Beans(
                    rsts.getInt("id"),
                    rsts.getString("persona"),
                    rsts.getString("sql"),
                    rsts.getTimestamp("fecha"));
            list.add(beans);
        }
        //Desconecta de la base de datos debido a que es un resultset y podria quedar la conexion activa
        persistencia.dbDisconnect();
        return list;
    }

    public String strChar(String data) {
        data = data.toLowerCase().trim();
        data = data.replaceAll("á", "a");
        data = data.replaceAll("é", "e");
        data = data.replaceAll("í", "i");
        data = data.replaceAll("ó", "o");
        data = data.replaceAll("ú", "u");
        data = data.replaceAll("a", "[a,á]");
        data = data.replaceAll("e", "[e,é]");
        data = data.replaceAll("i", "[i,í]");
        data = data.replaceAll("o", "[o,ó]");
        data = data.replaceAll("u", "[u,ú]");
        return data;
    }

    @Override
    public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {
        if (submittedValue.trim().equals("0")) {
            return null;
        }
        return null;
    }

    @Override
    public String getAsString(FacesContext facesContext, UIComponent component, Object value) {
        if (value == null || value.equals("")) {
            return "";
        }
        return String.valueOf(((person.general.Beans) value).getId());
    }
}
